home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HAM Radio 3.2
/
Ham Radio Version 3.2 (Chestnut CD-ROMs)(1993).ISO
/
packet
/
n17jsrc
/
kiss.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-06-03
|
4KB
|
205 lines
/* Routines for AX.25 encapsulation in KISS TNC
* Copyright 1991 Phil Karn, KA9Q
*
* Modified by G1EMM 19/11/90 to support multi-port KISS mode.
*/
/* Mods by G1EMM */
#include "global.h"
#include "mbuf.h"
#include "iface.h"
#include "kiss.h"
#include "devparam.h"
#include "slip.h"
#include "asy.h"
#include "ax25.h"
/* Send raw data packet on KISS TNC */
int
kiss_raw(iface,data)
struct iface *iface;
struct mbuf *data;
{
register struct mbuf *bp;
/* Put type field for KISS TNC on front */
if((bp = pushdown(data,1)) == NULLBUF){
free_p(data);
return -1;
}
bp->data[0] = PARAM_DATA;
bp->data[0] |= (iface->port << 4);
if(iface->port){
iface->rawsndcnt++;
iface->lastsent = Clock;
}
/* slip_raw also increments sndrawcnt */
slip_raw(Slip[iface->xdev].iface,bp);
return 0;
}
/* Process incoming KISS TNC frame */
void
kiss_recv(iface,bp)
struct iface *iface;
struct mbuf *bp;
{
char kisstype;
struct iface *kissif;
int port;
kisstype = PULLCHAR(&bp);
port = kisstype >> 4;
if((kissif = Slip[iface->xdev].kiss[port]) == NULLIF){
free_p(bp);
return;
}
switch(kisstype & 0xf){
case PARAM_DATA:
ax_recv(kissif,bp);
break;
default:
free_p(bp);
break;
}
}
/* Perform device control on KISS TNC by sending control messages */
int32
kiss_ioctl(iface,cmd,set,val)
struct iface *iface;
int cmd;
int set;
int32 val;
{
struct mbuf *hbp;
char *cp;
int rval = 0;
/* At present, only certain parameters are supported by
* stock KISS TNCs. As additional params are implemented,
* this will have to be edited
*/
switch(cmd){
case PARAM_RETURN:
set = 1; /* Note fall-thru */
case PARAM_TXDELAY:
case PARAM_PERSIST:
case PARAM_SLOTTIME:
case PARAM_TXTAIL:
case PARAM_FULLDUP:
case PARAM_HW:
if(!set){
rval = -1; /* Can't read back */
break;
}
/* Allocate space for cmd and arg */
if((hbp = alloc_mbuf(2)) == NULLBUF){
free_p(hbp);
rval = -1;
break;
}
cp = hbp->data;
*cp++ = cmd;
*cp = val;
hbp->cnt = 2;
if(hbp->data[0] != (char) PARAM_RETURN)
hbp->data[0] |= (iface->port << 4);
if(iface->port){
iface->rawsndcnt++;
iface->lastsent = Clock;
}
/* Even more "raw" than kiss_raw */
slip_raw(Slip[iface->xdev].iface,hbp);
/* slip_raw(iface,hbp); / * Even more "raw" than kiss_raw */
rval = val;
break;
case PARAM_SPEED: /* These go to the local asy driver */
case PARAM_DTR:
case PARAM_RTS:
rval = asy_ioctl(iface,cmd,set,val);
break;
default: /* Not implemented */
rval = -1;
break;
}
return rval;
}
int
kiss_stop(iface)
struct iface *iface;
{
Slip[iface->xdev].kiss[iface->port] = NULLIF;
return 0;
}
/* Attach a kiss interface to an existing asy interface in the system
* argv[0]: hardware type, must be "kiss"
* argv[1]: master interface, e.g., "ax4"
* argv[2]: kiss port, e.g., "4"
* argv[3]: interface label, e.g., "ax0"
* argv[4]: maximum transmission unit, bytes
*/
int
kiss_attach(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *if_asy, *if_kiss;
int port;
if((if_asy = if_lookup(argv[1])) == NULLIF){
tprintf("Interface %s does not exist\n",argv[1]);
return -1;
}
if(if_lookup(argv[3]) != NULLIF){
tprintf("Interface %s already exists\n",argv[4]);
return -1;
}
if((port = atoi(argv[2])) == 0){
tprintf("Port 0 automatically assigned to interface %s\n",argv[1]);
return -1;
}
if(port < 1 || port > 15){
tprintf("Ports 1 to 15 only\n");
return -1;
}
if(Slip[if_asy->xdev].kiss[port] != NULLIF){
tprintf("Port %d already allocated on interface %s\n", port, argv[1]);
return -1;
}
/* Create interface structure and fill in details */
if_kiss = (struct iface *)callocw(1,sizeof(struct iface));
if_kiss->addr = if_asy->addr;
if_kiss->name = strdup(argv[3]);
if(argc >= 5){
if_kiss->mtu = atoi(argv[4]);
} else {
if_kiss->mtu = if_asy->mtu;
}
if_kiss->dev = if_asy->dev;
if_kiss->stop = kiss_stop;
setencap(if_kiss,"AX25");
if_kiss->ioctl = kiss_ioctl;
if_kiss->raw = kiss_raw;
if(if_kiss->hwaddr == NULLCHAR)
if_kiss->hwaddr = mallocw(AXALEN);
memcpy(if_kiss->hwaddr,Mycall,AXALEN);
if_kiss->xdev = if_asy->xdev;
if_kiss->next = Ifaces;
Ifaces = if_kiss;
if_kiss->port = port;
Slip[if_kiss->xdev].kiss[if_kiss->port] = if_kiss;
return 0;
}